# encoding: utf-8

import cv2
import cv2.cv as cv
import numpy as np
import matplotlib.pyplot as plt
import os,sys
import  re
import datetime


maxRadius=200
minRadius = 150



def get_color_distribution(img):
    print '-------------get_color_distribution---------------'
    print datetime.datetime.now()

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    hist_full = cv2.calcHist([gray],[0],None,[256],[0,256])

    return hist_full





def get_potic_cup(img):
    print '-------------get_potic_cup---------------'
    print datetime.datetime.now()

    GrayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    ret,thresh2=cv2.threshold(GrayImage,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

    for i in range(len(thresh2[0])):
        for j in range(len(thresh2[:,:2])):
            if thresh2[j][i] == 255:
                GrayImage[j][i] = 255

    optic_cup =cv2.threshold(GrayImage,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)[1]
    # plt.subplot(132)
    # plt.imshow(optic_cup,'gray')
    # plt.show()

    return  optic_cup


def get_circles_range(thresh1):


    not_check=[]

    yus = []
    def check(index_x,index_y):

        print '---------check'
        test_elements = [[index_x-1,index_y-1],[index_x-1,index_y],[index_x-1,index_y+1],[index_x,index_y-1],
                            [index_x,index_y+1],[index_x+1,index_y-1],
                            [index_x+1,index_y],
                            [index_x+1,index_y+1]
                            ]

        for element in test_elements:
            if element not in not_check:
                print '------check element-----'
                print element
                if thresh1[element[1]][element[0]] == 255:
                    yu.append(element)
                    will_check.append(element)
                not_check.append(element)
            else:
                print '----------had check'


    for index_y in range(1 ,(len(thresh1)-2)):
        for index_x in range(1,len(thresh1[1])-2):


            if [index_x,index_y] not in not_check:
                print '=======not in'
                print [index_x,index_y]
                will_check = []
                yu = []
                if thresh1[index_y][index_x] == 255:
                    will_check = [[index_x-1,index_y-1],[index_x-1,index_y],[index_x-1,index_y+1],[index_x,index_y-1],
                                [index_x,index_y+1],[index_x+1,index_y-1],
                                [index_x+1,index_y],
                                [index_x+1,index_y+1]
                                ]
                    for element in will_check:
                        # if element not in not_check :
                            check(element[0], element[1])
                    yus.append(yu)
            else:
                print '-----------------in'
                print [index_x,index_y]
    max_yu_length = 0
    ma_yu_index = -1
    for yu_index in range(len(yus)):
        print '------------'
        print yu_index
        if len(yus[yu_index])> max_yu_length:
            ma_yu_index = yu_index
            max_yu_length =len(yus[yu_index])
    a =yus[ma_yu_index]
    print np.mean(np.array(a)[:,0])
    print np.mean(np.array(a)[:,1])




def get_circles_range_1(thresh1):
    test = []
    for index_y in range(1 ,(len(thresh1)-2)):
        for index_x in range(1,len(thresh1[1])-2):
            if thresh1[index_y][index_x] == 255 and 900<index_y<1300:
                test.append([index_x,index_y])


    x = int(np.mean(np.array(test)[:,0]))
    y = int(np.mean(np.array(test)[:,1]))
    print x
    print y

    return [x,y]





def filter_circles(circles1,circle_center):
    circles = circles1[0, :, :]
    new_circles = []


    for circle in circles:
        if ((circle_center[0]-100<circle[0]<circle_center[0]+100 or circle_center[1]-100<circle[0]<circle_center[1]+100)):
            new_circles.append(circle)

    return  new_circles




def get_circles(img, hist):
    print '-------------get_circles---------------'
    print datetime.datetime.now()

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    xcolor = [i for i in range(len(hist)) if  hist[i]>=10000][-1]

    ret, thresh1 = cv2.threshold(gray, xcolor, 255, cv2.THRESH_BINARY)





    circles1 = cv2.HoughCircles(thresh1, cv.CV_HOUGH_GRADIENT, 8, 300, param1=180, param2=180, minRadius=minRadius, maxRadius=maxRadius)
    circle_center = get_circles_range_1(thresh1)
    while (circles1 == None or len(filter_circles(circles1, circle_center))==0):

        xcolor = xcolor - 1
        ret,thresh1 = cv2.threshold(gray, xcolor, 255, cv2.THRESH_BINARY)
        circles1 = cv2.HoughCircles(thresh1, cv.CV_HOUGH_GRADIENT, 8, 300, param1=180, param2=180, minRadius=minRadius, maxRadius=maxRadius)
        circle_center = get_circles_range_1(thresh1)

    circles = filter_circles(circles1,circle_center)

    circles = np.uint16(np.around(circles))  # 四舍五入，取整






    return {'thresh1': thresh1,
            'circles': circles,
            'circle_center': circle_center
            }


def get_circle(img,circles,thresh1):
    print '-------------get_circle---------------'
    print datetime.datetime.now()
    max_length = 0
    max_circle_index = -1
    max_y = len(img)
    max_x = len(img[1])
    for index, circle in enumerate(circles[:]):
        length = 0

        radius = np.around(circle[2])
        for x in range((circle[0] - radius), (circle[0] + radius)):
            for y in range((circle[1] - circle[2]), (circle[1] + circle[2])):

                if  max_y > y and max_x > x and x >0 and y >0 and thresh1[y][x] == 255 and (np.square((x - circle[0])) + np.square((y - circle[1])) < np.square(radius)):
                    length = length + 1
        if length > max_length:
            max_length = length
            max_circle_index = index

    circle = circles[max_circle_index]
    return  circle


def get_radius(circle, thresh1):

    print '-------------get_radius---------------'
    print datetime.datetime.now()

    status = True
    add_radius = 0
    while status and add_radius<80:
        status = False
        radius = np.around(circle[2]) + add_radius + 1

        current_radius = radius-2
        current_x_start =  circle[0]-current_radius
        current_x_end = circle[0]+current_radius
        current_y_start =  circle[1]-current_radius
        current_y_end = circle[1]+current_radius


        x_start =  circle[0]-radius
        x_end = circle[0]+radius
        y_start =  circle[1]-radius
        y_end = circle[1]+radius

        #
        for x in range(x_start, x_end):
            for y in range(y_start,y_end):

               if thresh1[y][x]==255 and (x_start<x<current_x_start or y_end>y>current_y_end or x_end> x> current_x_end or current_y_start>y>y_start):
                    status =   True
                    break
            if status:
                break
        if status:
            add_radius =add_radius + 2
        else:
            add_radius = add_radius - 1


    return   circle[2] + add_radius

def get_cup_radius(circle,radius,optic_cup):
    print '-------------get_cup_radius---------------'
    print datetime.datetime.now()
    x_start = circle[0]-radius
    x_end = circle[0]+radius
    y_start = circle[1]-radius
    y_end = circle[1]+radius


    A = optic_cup[y_start:y_end, x_start:x_end]
    cup_y_start = 0
    cup_y_end = 0
    cup_start={'x':0,'y':0}
    cup_end={'x':0,'y':0}
    for i in range(len(A[:])):

        for start_x_index, j in enumerate(A[i][:]):
            if j == 0:
              cup_y_start = i
            if cup_y_start !=0 :
                cup_start={'x':start_x_index +x_start,'y':i+y_start}
                break
        if cup_y_start !=0 :
                break
    for m  in reversed(range(len(A[:]))):
        for end_x_index ,n in enumerate(A[m][:]):
            if n == 0:
                cup_y_end = m
                if cup_y_end !=0 :
                    cup_end = {'x':end_x_index+x_start,'y':m+y_start}
                    break
        if cup_y_end !=0 :
                break
    cup_radius = cup_y_end - cup_y_start
    return {'cup_radius':cup_radius,'cup_start':cup_start, 'cup_end':cup_end}





def compute(path):


    img = cv2.imread(path)
    optic_cup = get_potic_cup(img)



    hist = get_color_distribution(img)
    circles_info = get_circles(img, hist)


    circles = circles_info['circles']
    thresh1 = circles_info['thresh1']


    circle = get_circle(img, circles, thresh1)
    print circle


    radius = get_radius(circle, thresh1)

    if radius>=220:
        radius = get_cup_radius(circle,radius, thresh1)['cup_radius']/2

    print '-------------------计算cup-radius--------------------'
    cup_radius_info = get_cup_radius(circle,radius,optic_cup)


    cup_radius = cup_radius_info['cup_radius']
    plt.figure(figsize=(11,11))
    plt.subplot(121)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    cup_start = ((cup_radius_info['cup_start']['x']+cup_radius_info['cup_end']['x'])/2,cup_radius_info['cup_start']['y'] )
    cup_end = ((cup_radius_info['cup_start']['x']+cup_radius_info['cup_end']['x'])/2,cup_radius_info['cup_end']['y'] )

    cv2.line(gray,cup_start,cup_end,(255,0,0),5)
    fine_tune = -30

    x_start = circle[0]-radius
    x_end = circle[0]+radius
    y_start = circle[1]-radius
    y_end = circle[1]+radius


    for index_y in range(len(optic_cup[y_start:y_end])):
        for index_x in range(len(optic_cup[y_start+index_y][x_start:x_end])):
            if optic_cup[y_start+index_y][x_start+index_x] ==0:

                gray[y_start+index_y][x_start+index_x] =255


    if circle[0]>1800:
        fine_tune = 30



    cv2.circle(gray, (circles_info['circle_center'][0]+fine_tune, circles_info['circle_center'][1]), radius, (255, 0, 0), 5)
    cv2.circle(thresh1, (circles_info['circle_center'][0]+fine_tune, circles_info['circle_center'][1]), radius, (255, 0, 0), 5)
    plt.title(path)
    plt.imshow(gray,'gray')





    print datetime.datetime.now()


    print '-------------------杯盘比---------------------'
    print datetime.datetime.now()
    print '-----图片:'+ path
    # print cup_radius
    print 2*radius
    ratio =  round((float(cup_radius) / (2*radius)),3)
    print ratio
    #
    return  {'ratio': ratio, 'path':path}


def getFileList( file_path ):
        files = os.listdir( file_path )
        imgs =[]
        for file in files :
          if re.search('.jpg',file):
            imgs.append(file)
        return imgs



file_path =  os.getcwd()
imags = getFileList(file_path)
results = []





for index, img in enumerate(imags):

    result = compute(img)

    results.append(result)
plt.show()


# print '------------results'
# print results
































